package com.xdf.service.impl;

import com.alibaba.fastjson.JSON;
import com.xdf.constant.AuthorityConstant;
import com.xdf.constant.CommonConstant;
import com.xdf.entity.SysUser;
import com.xdf.service.JWTService;
import com.xdf.service.SysUserService;
import com.xdf.utils.RSAUtils;
import com.xdf.vo.LoginUserInfo;
import com.xdf.vo.UsernameAndPassword;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.ChronoUnit;
import java.util.Date;
import java.util.Optional;
import java.util.UUID;


/**
 * @author chanchaw
 * @create 2025-08-22 9:15
 */
@RequiredArgsConstructor
@Slf4j
@Service
@Transactional(rollbackFor = Exception.class)
public class JWTServiceImpl implements JWTService {
    private final SysUserService sysUserService;
    @Override
    public String generateToken(String username, String password) throws Exception {
        return generateToken(username,password,AuthorityConstant.DEFAULT_EXPIRE_HOUR);// 默认过期时长
    }

    @Override
    public String generateToken(String username, String password, int expire) throws Exception {
        SysUser sysUser = sysUserService.checkPwd(username, password);
        if(expire <= 0) expire = AuthorityConstant.DEFAULT_EXPIRE_HOUR;

        LoginUserInfo loginUserInfo = new LoginUserInfo();
        loginUserInfo.setId(sysUser.getId());
        loginUserInfo.setUsername(sysUser.getUsername());

        // token超时的时间点
//        ZonedDateTime zdt = LocalDateTime.now().plus(expire, ChronoUnit.HOURS).atStartOfDay(ZoneId.systemDefault());
        ZonedDateTime zdt = LocalDateTime.now().plus(expire, ChronoUnit.HOURS).atZone(ZoneId.systemDefault());
        Date expiredDate = Date.from(zdt.toInstant());

        String token = Jwts.builder()
                // jwt payload = kv对象
                .claim(CommonConstant.JWT_USER_INFO_KEY, JSON.toJSONString(loginUserInfo))
                // token.id
                .setId(UUID.randomUUID().toString())
                // token 过期时间
                .setExpiration(expiredDate)
                // 使用私钥签名
                .signWith(RSAUtils.getPrivateKey(AuthorityConstant.PRIVATE_KEY), SignatureAlgorithm.RS256)
                .compact();
        return token;
    }

    /**
     * 注册新用户并获取返回 token
     * @param usernameAndPassword
     * @return
     */
    @Override
    public String registerUserAndGenerateToken(UsernameAndPassword usernameAndPassword) throws Exception {
        if(usernameAndPassword == null) throw new RuntimeException("空数据无法注册");
        String username = Optional.ofNullable(usernameAndPassword.getUsername()).orElse("");
        if(username.length() == 0) throw new RuntimeException("用户名不可为空！");

        String password = Optional.ofNullable(usernameAndPassword.getPassword()).orElse("");
        if(password.length() == 0) throw new RuntimeException("密码不可为空！");

        SysUser sysUser = sysUserService.get8Username(username);
        if(sysUser != null) throw new RuntimeException("用户名已经存在，请更换用户名后再试！");
        sysUser = new SysUser();
        sysUser.setUsername(username);
        sysUser.setPassword(password);

        sysUserService.insert(sysUser);
        return generateToken(username,password);
    }
}
